﻿using System;
using UnityEngine;
using UnityExtensions;

public class SingleInstanceMono<T>: SingleInstance<T> where T : MonoBehaviour,new()
{
	public static GameObject MainObj;
	private static string mGobjName = "Main";
	public static T GetInstance(string gobjName)
	{
		mGobjName = gobjName;
		return SingleInstance<T>.GetInstance(GetInstanceDefault, null);
	}
	public new static T GetInstance()
	{
		return SingleInstance<T>.GetInstance(GetInstanceDefault, null);
	}

	private static T GetInstanceDefault()
	{
		var main = MainObj;
		if (MainObj == null)
		{
			main = GameObjectUtility.FindOrNew(mGobjName);
			MainObj = main;
		}
		var com = main.GetComponentOrAdd<T>();
		return com;
	}
}
public class SingleInstance<T> where T : new()
{
	private static bool sIsInstanted = false;
	private static T sInstance;
	private static readonly object sLocker = new object();
	private static Func<T> sInstanterFunc;
	private static Action<T> sInstanceInitAction;
	public static T GetInstance(Func<T> instanterFunc, Action<T> instanceInitAction)
	{
		if (sIsInstanted) return sInstance;

		lock (sLocker)
		{
			if (sIsInstanted) return sInstance;

			sInstance = instanterFunc == null ? new T() : instanterFunc();
			if (instanceInitAction != null)
			{
				instanceInitAction(sInstance);
			}

			sIsInstanted = true;
		}
		return sInstance;
	}

	public void SetInstanceInitAction(Action<T> v)
	{
		sInstanceInitAction = v;
	}

	public void SetInstanterFunc(Func<T> v)
	{
		sInstanterFunc = v;
	}

	public static T GetInstance()
	{
		return GetInstance(sInstanterFunc, sInstanceInitAction);
	}
	public static T Instance
	{
		get
		{
			return GetInstance();
		}
	}

	public static void Release()
	{
		sIsInstanted = false;
		sInstance = default(T);
	}

}

